

#import "NSString+Extension.h"
#import <CommonCrypto/CommonDigest.h>
#import <objc/runtime.h>
#import <sys/utsname.h>
#import <CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CommonCrypto/CommonCryptor.h>

@implementation NSString (Extension)
// 获取设备型号
+ (NSString *)getDeviceModel{
    struct utsname systemInfo;
    uname(&systemInfo);
    NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding];
    if([platform isEqualToString:@"iPhone1,1"]) return@"iPhone 2G";
    if([platform isEqualToString:@"iPhone1,2"]) return@"iPhone 3G";
    if([platform isEqualToString:@"iPhone2,1"]) return@"iPhone 3GS";
    if([platform isEqualToString:@"iPhone3,1"]) return@"iPhone 4";
    if([platform isEqualToString:@"iPhone3,2"]) return@"iPhone 4";
    if([platform isEqualToString:@"iPhone3,3"]) return@"iPhone 4";
    if([platform isEqualToString:@"iPhone4,1"]) return@"iPhone 4S";
    if([platform isEqualToString:@"iPhone5,1"]) return@"iPhone 5";
    if([platform isEqualToString:@"iPhone5,2"]) return@"iPhone 5";
    if([platform isEqualToString:@"iPhone5,3"]) return@"iPhone 5c";
    if([platform isEqualToString:@"iPhone5,4"]) return@"iPhone 5c";
    if([platform isEqualToString:@"iPhone6,1"]) return@"iPhone 5s";
    if([platform isEqualToString:@"iPhone6,2"]) return@"iPhone 5s";
    if([platform isEqualToString:@"iPhone7,1"]) return@"iPhone 6 Plus";
    if([platform isEqualToString:@"iPhone7,2"]) return@"iPhone 6";
    if([platform isEqualToString:@"iPhone8,1"]) return@"iPhone 6s";
    if([platform isEqualToString:@"iPhone8,2"]) return@"iPhone 6s Plus";
    if([platform isEqualToString:@"iPhone8,4"]) return@"iPhone SE";
    if([platform isEqualToString:@"iPhone9,1"]) return@"iPhone 7";
    if([platform isEqualToString:@"iPhone9,2"]) return@"iPhone 7 Plus";
    if([platform isEqualToString:@"iPhone10,1"])return@"iPhone 8";
    if([platform isEqualToString:@"iPhone10,4"])return@"iPhone 8";
    if([platform isEqualToString:@"iPhone10,2"])return@"iPhone 8 Plus";
    if([platform isEqualToString:@"iPhone10,5"])return@"iPhone 8 Plus";
    if([platform isEqualToString:@"iPhone10,3"])return@"iPhone X";
    if([platform isEqualToString:@"iPhone10,6"])return@"iPhone X";
    //新添加
    if([platform isEqualToString:@"iPhone11,8"])return@"iPhone XR";
    if([platform isEqualToString:@"iPhone11,2"])return@"iPhone XS";
    if([platform isEqualToString:@"iPhone11,4"])return@"iPhone XS Max";
    if([platform isEqualToString:@"iPhone11,6"])return@"iPhone XS Max";
    if([platform isEqualToString:@"iPhone12,1"])return@"iPhone 11";
    if([platform isEqualToString:@"iPhone12,3"])return@"iPhone 11 Pro";
    if([platform isEqualToString:@"iPhone12,5"])return@"iPhone 11 Pro Max";
    if([platform isEqualToString:@"iPhone12,8"])return@"iPhone SE 2020";
    if([platform isEqualToString:@"iPhone13,1"])return@"iPhone 12 mini";
    if([platform isEqualToString:@"iPhone13,2"])return@"iPhone 12";
    if([platform isEqualToString:@"iPhone13,3"])return@"iPhone 12 Pro";
    if([platform isEqualToString:@"iPhone13,4"])return@"iPhone 12 Pro Max";
    if([platform isEqualToString:@"iPhone14,4"])return@"iPhone 13 mini";
    if([platform isEqualToString:@"iPhone14,5"])return@"iPhone 13";
    if([platform isEqualToString:@"iPhone14,2"])return@"iPhone 13 Pro";
    if([platform isEqualToString:@"iPhone14,3"])return@"iPhone 13 Pro Max";
    
    //结束
    if([platform isEqualToString:@"iPod1,1"]) return@"iPod Touch 1G";
    if([platform isEqualToString:@"iPod2,1"]) return@"iPod Touch 2G";
    if([platform isEqualToString:@"iPod3,1"]) return@"iPod Touch 3G";
    if([platform isEqualToString:@"iPod4,1"]) return@"iPod Touch 4G";
    if([platform isEqualToString:@"iPod5,1"]) return@"iPod Touch 5G";
    if([platform isEqualToString:@"iPad1,1"]) return@"iPad 1G";
    if([platform isEqualToString:@"iPad2,1"]) return@"iPad 2";
    if([platform isEqualToString:@"iPad2,2"]) return@"iPad 2";
    if([platform isEqualToString:@"iPad2,3"]) return@"iPad 2";
    if([platform isEqualToString:@"iPad2,4"]) return@"iPad 2";
    if([platform isEqualToString:@"iPad2,5"]) return@"iPad Mini 1G";
    if([platform isEqualToString:@"iPad2,6"]) return@"iPad Mini 1G";
    if([platform isEqualToString:@"iPad2,7"]) return@"iPad Mini 1G";
    if([platform isEqualToString:@"iPad3,1"]) return@"iPad 3";
    if([platform isEqualToString:@"iPad3,2"]) return@"iPad 3";
    if([platform isEqualToString:@"iPad3,3"]) return@"iPad 3";
    if([platform isEqualToString:@"iPad3,4"]) return@"iPad 4";
    if([platform isEqualToString:@"iPad3,5"]) return@"iPad 4";
    if([platform isEqualToString:@"iPad3,6"]) return@"iPad 4";
    if([platform isEqualToString:@"iPad4,1"]) return@"iPad Air";
    if([platform isEqualToString:@"iPad4,2"]) return@"iPad Air";
    if([platform isEqualToString:@"iPad4,3"]) return@"iPad Air";
    if([platform isEqualToString:@"iPad4,4"]) return@"iPad Mini 2G";
    if([platform isEqualToString:@"iPad4,5"]) return@"iPad Mini 2G";
    if([platform isEqualToString:@"iPad4,6"]) return@"iPad Mini 2G";
    if([platform isEqualToString:@"iPad4,7"]) return@"iPad Mini 3";
    if([platform isEqualToString:@"iPad4,8"]) return@"iPad Mini 3";
    if([platform isEqualToString:@"iPad4,9"]) return@"iPad Mini 3";
    if([platform isEqualToString:@"iPad5,1"]) return@"iPad Mini 4";
    if([platform isEqualToString:@"iPad5,2"]) return@"iPad Mini 4";
    if([platform isEqualToString:@"iPad5,3"]) return@"iPad Air 2";
    if([platform isEqualToString:@"iPad5,4"]) return@"iPad Air 2";
    if([platform isEqualToString:@"iPad6,3"]) return@"iPad Pro 9.7";
    if([platform isEqualToString:@"iPad6,4"]) return@"iPad Pro 9.7";
    if([platform isEqualToString:@"iPad6,7"]) return@"iPad Pro 12.9";
    if([platform isEqualToString:@"iPad6,8"]) return@"iPad Pro 12.9";
    if([platform isEqualToString:@"i386"]) return@"iPhone Simulator";
    if([platform isEqualToString:@"x86_64"]) return@"iPhone Simulator";
    return platform;
}

+(NSString *)md5:(NSString *)str {
    const char *cStr = [str UTF8String];
    unsigned char result[16];
    CC_MD5(cStr, strlen(cStr), result); // This is the md5 call
    return [NSString stringWithFormat:
            @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
            result[0], result[1], result[2], result[3],
            result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11],
            result[12], result[13], result[14], result[15]
            ];
}

// 获取当前系统版本号
+ (NSString *)getSystemVersion
{
    NSString *systemVersion = [[UIDevice currentDevice] systemVersion];
    return systemVersion;
}

// 获取设备IDFV
+ (NSString *)getDeviceIDFV
{
    return [UIDevice currentDevice].identifierForVendor.UUIDString;
}

// 获取运营商信息
+ (NSString *)getCarrierInfo
{
    CTTelephonyNetworkInfo *telephonyInfo = [[CTTelephonyNetworkInfo alloc] init];
    CTCarrier *carrier = [telephonyInfo subscriberCellularProvider];
    NSString *carrierName=[carrier carrierName];
    return kStringIsEmpty(carrierName)?@"无":carrierName;
}

+ (NSString*)stringToSHA1:(NSString *)str{
    // 转化位cstring 或者类似MD5的方式也行 const char *cstr = [str UTF8String];
    const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding];
    // 生成对应的NSData对象
    NSData *data = [NSData dataWithBytes:cstr length:str.length];
    // 创建一个20个位的1字节数组
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
    // 转化为对应的16进制数字
    CC_SHA1(data.bytes, (unsigned int)data.length, digest);
    // 声明一个40字符的string对象
    NSMutableString *result = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH *2];
    // 组装加密结果
    for (int i = 0 ; i < CC_SHA1_DIGEST_LENGTH; i++) {
        [result appendFormat:@"%02x",digest[i]];
    }
    return result;
}

+ (NSString *)formInputSign:(NSDictionary *)params{
    NSString *string = @"";
    NSArray *keys = [params allKeys];
    // 1) 将传递的参数按参数名从小到大排序
    NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        return [obj1 compare:obj2 options:NSNumericSearch];
    }];
    //2) 再将参数按key=base64(value)加&拼接成字符串str
    for (NSString *key in sortedArray) {
        NSString *value = [params objectForKey:key];
        NSData *vdata = [value dataUsingEncoding:NSUTF8StringEncoding];
        NSString *encodeStr = [vdata base64EncodedStringWithOptions:0];
        if ([string isEqualToString:@""]) {
            string = [NSString stringWithFormat:@"%@=%@",key,encodeStr];
        }else{
            string = [NSString stringWithFormat:@"%@&%@=%@",string,key,encodeStr];
        }
    }
    //3) 在将str += "&key="+appsecret;
    NSString *result = [NSString stringWithFormat:@"%@&key=%@",string,AppSecret];
    //4) 最后把str进行sha1加密
    return [NSString stringToSHA1:result];
}

//十六进制字符串转数字
+ (NSInteger)numberWithHexString:(NSString *)hexString{

const char *hexChar = [hexString cStringUsingEncoding:NSUTF8StringEncoding];

int hexNumber;

sscanf(hexChar, "%x", &hexNumber);

return (NSInteger)hexNumber;

}


// 解密
+ (NSString*)decryptWithContent:(NSString*)content key:(NSString*)aKey iv:(NSString*)iv {
   const char * contentChar =[content UTF8String];
   char * keyChar =(char*)[aKey UTF8String];
   char * ivChar =(char*)[iv UTF8String];
   const char *miChar;
   miChar = encryptWithKeyAndType(contentChar, 1, keyChar,ivChar);
   return  [NSString stringWithCString:miChar encoding:NSUTF8StringEncoding];
}

static const char* encryptWithKeyAndType(const char *text,CCOperation encryptOperation,char *key, char *ivStr) {
   NSString *textString=[[NSString alloc]initWithCString:text encoding:NSUTF8StringEncoding];
   const void *dataIn;
   size_t dataInLength;
    if (encryptOperation == kCCDecrypt) {//传递过来的是decrypt 解码
       //解码 base64
       NSData *decryptData = [GTMBase64 decodeData:[textString dataUsingEncoding:NSUTF8StringEncoding]];//转成utf-8并decode
       dataInLength = [decryptData length];
       dataIn = [decryptData bytes];
    } else {  //encrypt
       NSData* encryptData = [textString dataUsingEncoding:NSUTF8StringEncoding];
       dataInLength = [encryptData length];
       dataIn = (const void *)[encryptData bytes];
   }
   CCCryptorStatus ccStatus;
   uint8_t *dataOut = NULL; //可以理解位type/typedef 的缩写（有效的维护了代码，比如：一个人用int，一个人用long。最好用typedef来定义）
   size_t dataOutAvailable = 0; //size_t  是操作符sizeof返回的结果类型
   size_t dataOutMoved = 0;
   dataOutAvailable = (dataInLength + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);
   dataOut = malloc( dataOutAvailable * sizeof(uint8_t));
   memset((void *)dataOut, 00, dataOutAvailable);//将已开辟内存空间buffer的首 1 个字节的值设为值 0
   const void *vkey = key;//密钥
   const void *iv = (const void *) ivStr; //矢量
   //CCCrypt函数 加密/解密
   ccStatus = CCCrypt(encryptOperation,      //  加密/解密
                      kCCAlgorithmDES,       //  加密根据哪个标准（des，3des，aes。。。。）
                      kCCOptionPKCS7Padding, //  选项分组密码算法(des:对每块分组加一次密  3DES：对每块分组加三个不同的密)
                      vkey,                  //  密钥  加密和解密的密钥必须一致
                      kCCKeySizeDES,         //  DES 密钥的大小（kCCKeySizeDES=8）
                      iv,                    //  可选的初始矢量
                      dataIn,                //  数据的存储单元
                      dataInLength,          //  数据的大小
                      (void *)dataOut,       //  用于返回数据
                      dataOutAvailable,
                      &dataOutMoved);
    NSString *result = nil;
    if (encryptOperation == kCCDecrypt) { //encryptOperation==1  解码
       //得到解密出来的data数据，改变为utf-8的字符串
       result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved] encoding:NSUTF8StringEncoding];
    } else { //encryptOperation==0  （加密过程中，把加好密的数据转成base64的）
       //编码 base64
       NSData *data = [NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved];
       result = [GTMBase64 stringByEncodingData:data];
   }
   return [result UTF8String];

}

+ (NSDictionary *)convertjsonStringToDict:(NSString *)jsonString {
    NSDictionary *retDict = nil;
   if ([jsonString isKindOfClass:[NSString class]]) {
       NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
       retDict = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:NULL];
       return  retDict;
   } else {
       return retDict;
   }
}


@end
